package cool.taomu.software.fig.asm.utils

import org.objectweb.asm.Opcodes
import org.objectweb.asm.Type
import org.objectweb.asm.commons.GeneratorAdapter
import org.objectweb.asm.commons.Method

class BytecodeUtils {
    /**
     * 构建返回值
     */
    def static void buildReturnValue(java.lang.reflect.Method m, FigGeneratorAdapter ga) {
        switch (m.returnType) {
            case int: {
                ga.checkCast(Integer);
                ga.invokeVirtual(Integer, "int intValue()");
            }
            case long: {
                ga.checkCast(Long);
                ga.invokeVirtual(Long, "long longValue()");
            }
            case double: {
                ga.checkCast(Double);
                ga.invokeVirtual(Double, "double doubleValue()");
            }
            case float: {
                ga.checkCast(Float);
                ga.invokeVirtual(Float, "float floatValue()");
            }
            case boolean: {
                ga.checkCast(Boolean);
                ga.invokeVirtual(Boolean, "boolean booleanValue()");
            }
            case short: {
                ga.checkCast(Short);
                ga.invokeVirtual(Short, "short shortValue()");
            }
            case char: {
                ga.checkCast(Character);
                ga.invokeVirtual(Character, "char charValue()");
            }
            case byte: {
                ga.checkCast(Byte);
                ga.invokeVirtual(Byte, "byte byteValue()");
            }
            case void: {
            }
            default: {
                ga.checkCast(m.returnType);
            }
        }
    }

    /**
     * 构建AspectHandle的参数
     */
    def static void buildArguments(Method method, FigGeneratorAdapter ga) {
        if (method.argumentTypes.size > 0) {
            for (var index = 0; index < method.argumentTypes.size; index++) {
                ga.dup;
                ga.push(index);
                switch (method.argumentTypes.get(index).descriptor) {
                    case "Z": {
                        ga.loadArg(index);
                        ga.invokeStatic(Boolean, "Boolean valueOf(boolean)");
                    }
                    case "C": {
                        ga.loadArg(index);
                        ga.invokeStatic(Character, "Character valueOf(char)");
                    }
                    case "B": {
                        ga.loadArg(index);
                        ga.invokeStatic(Byte, "Byte valueOf(byte)");
                    }
                    case "S": {
                        ga.loadArg(index);
                        ga.invokeStatic(Short, "Short valueOf(short)");
                    }
                    case "I": {
                        ga.loadArg(index);
                        ga.invokeStatic(Integer, "Integer valueOf(int)");
                    }
                    case "F": {
                        ga.loadArg(index);
                        ga.invokeStatic(Float, "Float valueOf(float)");
                    }
                    case "J": {
                        ga.loadArg(index);
                        ga.invokeStatic(Float, "Long valueOf(long)");
                    }
                    case "D": {
                        ga.loadArg(index);
                        ga.invokeStatic(Float, "Double valueOf(double)");
                    }
                    default: {
                        ga.visitVarInsn(Opcodes.ALOAD, index + 1);
                    }
                }
                ga.visitInsn(Opcodes.AASTORE);
            }

        } else {
            ga.visitInsn(Opcodes.ACONST_NULL);
        }
    }
}
